package com.joelemon.mockinfluxdbdata.utils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description: 计算工具
 * @Author: HJY
 * @Date: 2023/7/18
 */
public class CalcUtil {
    /**
     * 计算两数之和
     *
     * @param val
     * @return
     */
    public static Float add(Float ...val) {
        Float result = null;
        for (Float aFloat : val) {
            if (Objects.nonNull(aFloat)) {
                if (Objects.isNull(result)) {
                    result = aFloat;
                } else {
                    result += aFloat;
                }
            }
        }
        return result;
    }
    /**
     * 计算两数之和
     *
     * @param val
     * @return
     */
    public static Double add(Double ...val) {
        Double result = null;
        for (Double aValue : val) {
            if (Objects.nonNull(aValue)) {
                if (Objects.isNull(result)) {
                    result = aValue;
                } else {
                    result += aValue;
                }
            }
        }
        return result;
    }

    public static Double max(Double ...val) {
        if (val.length == 2) {
            if (Objects.isNull(val[0])) {
                return val[1];
            }
            if (Objects.isNull(val[1])) {
                return val[0];
            }
            if (Objects.nonNull(val[0]) && Objects.nonNull(val[1])) {
                return Math.max(val[0], val[1]);
            }
        }
        return Arrays.asList(val).stream().filter(Objects::nonNull).max(Double::compareTo).orElse(null);
    }
    public static Double min(Double ...val) {
        if (val.length == 2) {
            if (Objects.isNull(val[0])) {
                return val[1];
            }
            if (Objects.isNull(val[1])) {
                return val[0];
            }
            if (Objects.nonNull(val[0]) && Objects.nonNull(val[1])) {
                return Math.min(val[0], val[1]);
            }
        }
        return Arrays.asList(val).stream().filter(Objects::nonNull).min(Double::compareTo).orElse(null);
    }

    public static <T> List<T> mergeList(List<T> ...list) {
        return Arrays.asList(list).stream().filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toList());
    }

    public static <E,T> Map<E, List<T>> mergeMapList(Map<E, List<T>> ...mapData) {
        return Stream.of(mapData)
                .flatMap(map -> map.entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (list1, list2) -> CalcUtil.mergeList(list1, list2)));
    }
    public static <E,T> Map<E, T> mergeMapWithNullKey(Map<E, T> ...mapData) {
        if (mapData.length == 0) {
            return new HashMap<>();
        }
        Map<E, T> result = new HashMap<>();
        for (Map<E, T> map : mapData) {
            if (map == null) {
                continue;
            }
            for (E key : map.keySet()) {
                if (result.get(key) == null) {
                    result.put(key, map.get(key));
                }
            }
        }
        return result;
    }

    public static <E,T> Map<E, T> mergeMap(Map<E, T> ...mapData) {
        return Stream.of(mapData)
                .flatMap(map -> map.entrySet().stream())
                .filter(item -> item != null && item.getValue() != null && item.getKey() != null)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (val1, val2) -> val2));
    }
    public static <E,V,T> Map<E, Map<V, Map<E, T>>> mergeMapMap(Map<E, Map<V, Map<E, T>>> ...mapData) {
        return Stream.of(mapData)
                .flatMap(map -> map.entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (map1, map2) -> CalcUtil.mergeMap(map1, map2)));
    }

}
